# Python中的四大数据容器
# 列表list、元组tuple、字典dict、集合set

# 列表
# 定义：[元素1,元素2,元素3......]
# 特点：元素可以重复，元素的类型可以不唯一，有序的，可变的
list1 = [1, 2, 3, 4, 4, 5, 6, 6, 6, 'abc', True, 1.1]
print(list1)
print(type(list1))

# 常用方法
# 提取一个元素，传入一个索引
print(list1[9])
# 修改一个元素
print(list1[2])
list1[2] = 3.3
print(list1)

# 增加一个元素 到list的末尾
list1.append(10)
print(list1)
# 按照指定位置增加元素
list1.insert(2, 2.2)
print(list1)
# 移除一个元素
list1.pop()  # 移除最后一个元素
print(list1)
list1.pop(10)  # 按照指定位置移除元素
print(list1)
list1.remove(2.2)  # 按照指定的值移除元素
print(list1)
# 查找元素
print(list1.index(1.1))
print(list1.index(5))
# 在Python中 1 与 True ， 0 与 False 不严格区分，有些情况下时等价的
list1.remove(1)
print(list1)
print(list1.index(True))
# print(list1.index(False)) # 找不到 报错

list2 = [1, 2, 3]

print(list1 + list2)  # 返回新的list

# 会改变原有的list
list1.extend(list2)
print(list1)

# 倒转list
list1.reverse()
print(list1)
print(list1[::-1])  # 返回新的list

# 统计元素的数量
print(list1.count(6))

# 清空一个list
list1.clear()
print(list1)

# 排序
list2 = [2, 3, 4, 1, 8, 6, 7, 5]
print(list2)
list2.sort()
print(list2)
print("*" * 30)

# 元组Tuple
# 定义：(元素1,元素2,元素3......)
# 特点：元素可以重复，元素的类型可以不唯一，有序的，不可变的(一旦创建就不能修改)
tuple1 = (1, 2, 2, 2, 3, 4, 5, 'abc', True, False, 2.8)
print(tuple1)
print(type(tuple1))

print(tuple1[7])
# 只有两个常见的方法
# index、count

# 切片
# 提取有序数据容器中的元素
# 每个元素都有一个位置(索引，默认从左往右 从0开始)
# [起始位置:结束位置:步长]
# 起始位置 默认 为第一个元素的位置
# 结束位置 默认 为最后一个元素的位置
# 步长 默认 为1
# 位置支持负数索引
# 步长也可以为负数
list3 = [1, 2, 3, 4, 5, 6, 7]
tuple2 = (4, 5, 6, 7, 8, 9)
print(list3[1:4 + 1:1])  # [2, 3, 4, 5]
print(tuple2[1:3 + 1:1])  # (5, 6, 7)
print(list3[-2:-4 - 1:-1])  # [6, 5, 4]
print(list3[-4:-1:1])  # [4, 5, 6]

# 字典dict
# 定义：{k1:v1,k2:v2,k3:v3......}
# 特点：
# 1、字典中的元素都是KV格式的，类似Java中的Map
# 2、无序(没有索引)，可以通过Key获取Value
# 3、key是唯一的，如果出现相同的key，后面的value会覆盖前面的value
# 4、value可以是 任意类型：基本数据类型或者数据容器都可
# 5、key必须是不可变的(基本数据类型、元组tuple)
# 6、可变的

dict1 = {
    "k1": "v1",
    "k2": 1.1,
    0: '000',
    1: 100,
    1: 10000,
    2: 2,
    True: 'true',
    False: 'false',
    1.1: '1.1',
    (1, 2, 3): 'tuple',
    # [1,2,3]:'list',
    # {"k1":"v1"}:"dict",
}

# 不支持通过索引取元素
# 可以通过key取value
print(dict1[0])  # 在这里0并不是索引而是key
print(dict1['k1'])
print(dict1[1])

# 如果key中同时存在 0和False 或者 1和True
# 后面出现的值会覆盖前面的值
print(dict1[0])  # false
print(dict1[1])  # true
print(dict1[True])  # true
print(dict1[False])  # false

# 查看容器里面有多少个元素
# len()方法
print(len(dict1))

print(dict1)
print(type(dict1))

# dict 常见的操作
# 获取元素
print(dict1['k1'])
print(dict1.get('k1'))

# print(dict1['kk1'])  # 如果key不存在 则报错
print(dict1.get('kk1', 'key不存在时的返回值'))  # 如果key不存在 可以指定返回值 (推荐)

dict1.pop("k1")  # 按照指定的key移除KV
print(dict1)

print(dict1.keys())  # 获取字典中所有的key
print(dict1.values())  # 获取字典中所有的value
print(dict1.items())  # 获取字典中所有的KV

# 增加KV
dict1['kk1'] = 'vv1'

# 修改K对应的V
dict1['k2'] = 'v2'
print(dict1)

# 集合set
# 定义：{元素1,元素2,元素3......}
# 特点：元素唯一，会自动去重，无序，可变的，元素的类型可以不唯一
set1 = {1, 2, 2, 3, 4, 6, 7, 5, 8, 9, 9, 9}
print(set1)
print(type(set1))
print(len(set1))

# 集合之间的运算
# 交集、并集、差集
set2 = {1, 2, 3, 4, 5, 6}
set3 = {4, 5, 6, 7, 8, 9}

print(set2 & set3)  # 交集
print(set2 | set3)  # 并集
print(set2 - set3)  # 差集
print(set3 - set2)  # 差集

print(set1)
# 增加一个元素
set1.add(1)
set1.add(10)
print(set1)
# 移除一个元素
set1.pop()  # 随机的
set1.remove(7)  # 指定具体一个元素移除
print(set1)

# for"循环"
# 在Python中for一般用于遍历数据容器
list1 = [1, 2, 3, 4, 5]
tuple1 = (1, 2, 3, 4, 5)
dict1 = {"k1": "v1", "k2": "v2", "k3": "v3"}
set1 = {1, 2, 3, 4, 5}
# 通过缩进(4个空格)来区分代码块
for i in list1:
    print(i)

for i in tuple1:
    print(i)

for i in set1:
    print(i)

# 直接遍历字典只能获取key
for key in dict1:
    print(key)

# 同时获取KV
for key in dict1:
    print(key, dict1[key])
for kv in dict1.items():
    print(kv)
for k, v in dict1.items():
    print(k, v)

# for经常会同range一起使用
# range(起始位置,结束位置,步长) 用于生成序列
# 0 1 2
for i in range(3):
    print(i)
# 1 2 3
for i in range(1, 4):
    print(i)
# 1 3 5 7 9
for i in range(1, 10, 2):
    print(i)

# 列表推导式
# 列表是有一个表达式生成的
# 生成 1~10的list
list1_10 = []
for i in range(1, 11, 1):
    list1_10.append(i)
print(list1_10)
# 简写
print([i for i in range(1, 11, 1)])

# 1~100的list
print([i for i in range(1, 101)])
# 1~100所有的奇数组成的list
print([i for i in range(1, 101, 2)])
print([i for i in range(1, 101) if i % 2 == 1])
# 1~100所有的偶数组成的list
print([i for i in range(2, 101, 2)])
print([i for i in range(1, 101) if i % 2 == 0])

# 9 9 乘法表
print("\n".join(["\t".join(["{}*{}={}".format(i, j, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))
'''
list1_10 = []
for i in range(1, 11, 1):
    list1_10.append(i)
print(list1_10)
# 简写
print([i for i in range(1, 11, 1)])
'''
# 两个循环实现9 9 乘法表
# list_tmp2 = []
# for i in range(1, 10):
#     # list_tmp = []
#     # for j in range(1, i + 1):
#     #     # 格式化输出
#     #     list_tmp.append('{} * {} = {}'.format(i, j, i * j))
#     # print(list_tmp)
#     list_tmp2.append('\t'.join(['{} * {} = {}'.format(i, j, i * j) for j in range(1, i + 1)]))
# print("\n".join(list_tmp2))
# 简化
print("\n".join(['\t'.join(['{} * {} = {}'.format(i, j, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))

# while 循环
# 计算1~100的和 5050
i = 1
sum = 0
while i <= 100:
    # 通过缩进 4个空格 区分循环体
    sum += i
    i += 1
# 前面没有缩进 不在循环体中
print(sum)

# 计算1~100的和
# 当sum超过2000时就停止循环
i = 1
sum = 0
while i <= 100:
    # 通过缩进 4个空格 区分循环体
    sum += i
    i += 1
    if sum >= 2000:
        print(sum, i - 1)
        # 可以跳出循环
        break

# 计算1~100的奇数的和
i = 1
sum = 0
while i <= 100:
    # 通过缩进 4个空格 区分循环体
    if i % 2 == 0:
        i += 1
        # 可以跳过本次循环
        # 跳过时 需要注意循环条件也需要改变
        continue
    sum += i
    i += 1
print(sum)

# 选择结构
# if、else、elif
# 注意条件的先后顺序
# 在Python中没有switch

# 判断age 如果大于等于18则输出成年 年龄如果大于200则输出外星人 年龄如果小于0则输出不符合规范 否则输出未成年
# 接收用户输入
age = int(input("请输入年龄："))
if age > 200:
    print("外星人")
elif age < 0:
    print("年龄不符合规范")
elif age >= 18:
    print("成年")
else:
    print("未成年")
